/*
	Project:FFmpeg Media Source for Windows Media Foundation
	Part:Common
	File:MFSyncLock.h

	Creator:ShanYe (2014-06-16)
	Last Change:ShanYe (2014-06-16)
	Rev:1.0.0
*/

#pragma once

#include "stdafx.h"

class CCritSec
{
public:
	CRITICAL_SECTION cs;
public:
	CCritSec()
	{
		InitializeCriticalSectionEx(&cs,0,CRITICAL_SECTION_NO_DEBUG_INFO);
	}
	~CCritSec()
	{
		DeleteCriticalSection(&cs);
	}
public:
	void Lock()
	{
		EnterCriticalSection(&cs);
	}
	void Unlock()
	{
		LeaveCriticalSection(&cs);
	}
};

class CAutoLock
{
	CCritSec* cs;
public:
	CAutoLock(CCritSec* pcs)
	{
		cs = pcs;
		cs->Lock();
	}
	~CAutoLock()
	{
		cs->Unlock();
	}
};
#define AUTO_CRIT_SEC_LOCK_LINE_NAME(name,line) name##line
#define AUTO_CS_LOCK(cs) CAutoLock AUTO_CRIT_SEC_LOCK_LINE_NAME(lock,__LINE__)(cs)

class CEventSync
{
	HANDLE hEvent;
public:
	CEventSync(DWORD dwFlags = 0)
	{
		hEvent = CreateEventExW(NULL,NULL,dwFlags,EVENT_ALL_ACCESS);
	}
	~CEventSync()
	{
		CloseHandle(hEvent);
	}
public:
	operator HANDLE() const
	{
		return hEvent;
	}
public:
	BOOL Wait(DWORD dwWaitTimeout = INFINITE)
	{
		return WaitForSingleObjectEx(hEvent,dwWaitTimeout,FALSE) == WAIT_OBJECT_0 ? TRUE:FALSE;
	}
	VOID Set()
	{
		SetEvent(hEvent);
	}
	VOID Reset()
	{
		ResetEvent(hEvent);
	}
	BOOL Check()
	{
		return Wait(0);
	}
};

class CMutexSync
{
	HANDLE hMutex;
public:
	CMutexSync(DWORD dwFlags)
	{
		hMutex = CreateMutexExW(NULL,NULL,dwFlags,MUTEX_ALL_ACCESS);
	}
	~CMutexSync()
	{
		CloseHandle(hMutex);
	}
public:
	operator HANDLE() const
	{
		return hMutex;
	}
public:
	BOOL Wait(DWORD dwWaitTimeout = INFINITE)
	{
		return WaitForSingleObjectEx(hMutex,dwWaitTimeout,FALSE) == WAIT_OBJECT_0 ? TRUE:FALSE;
	}
	VOID Release()
	{
		ReleaseMutex(hMutex);
	}
};

class CSRWLock
{
public:
	SRWLOCK SRWLock;
public:
	CSRWLock()
	{
		InitializeSRWLock(&SRWLock);
	}
public:
	VOID LockShared()
	{
		AcquireSRWLockShared(&SRWLock);
	}
	VOID LockExclusive()
	{
		AcquireSRWLockExclusive(&SRWLock);
	}
	VOID UnlockShared()
	{
		ReleaseSRWLockShared(&SRWLock);
	}
	VOID UnlockExclusive()
	{
		ReleaseSRWLockExclusive(&SRWLock);
	}
	VOID TryLockShared()
	{
		TryAcquireSRWLockShared(&SRWLock);
	}
	VOID TryLockExclusive()
	{
		TryAcquireSRWLockExclusive(&SRWLock);
	}
};

class CCondVar
{
	CONDITION_VARIABLE cv;
public:
	CCondVar()
	{
		InitializeConditionVariable(&cv);
	}
public:
	BOOL SleepSRW(PSRWLOCK SRWLock,DWORD dwMilliseconds = INFINITE,BOOL bLockShared = FALSE)
	{
		return SleepConditionVariableSRW(&cv,SRWLock,dwMilliseconds,bLockShared ? CONDITION_VARIABLE_LOCKMODE_SHARED:0);
	}
	BOOL SleepCS(PCRITICAL_SECTION CriticalSection,DWORD dwMilliseconds = INFINITE)
	{
		return SleepConditionVariableCS(&cv,CriticalSection,dwMilliseconds);
	}
	VOID Wake()
	{
		WakeConditionVariable(&cv);
	}
	VOID WakeAll()
	{
		WakeAllConditionVariable(&cv);
	}
};